#include "table.h"
#include "entry.h"
#include "value.h"

#include <stdlib.h>
#include <string.h>


static const char * key_fcn(void * value)
{
	cconf_entry_t * e = value;
	return e->path;
}

static gdsl_element_t alloc_fcn(void * value)
{
	return (gdsl_element_t) value;
}

static void free_fcn(gdsl_element_t e)
{
	cconf_entry_free(e);
}

cconf_table_t * cconf_table_create(int size)
{
	cconf_table_t * t = calloc(1, sizeof(cconf_table_t));
	t->hash = gdsl_hash_alloc(NULL, &alloc_fcn, &free_fcn, &key_fcn, &gdsl_hash, size);
	t->keys = NULL;
	t->nkeys = 0;
	return t;
}

void cconf_table_free(void * table)
{
	int k;
	cconf_table_t * t = table;
	gdsl_hash_free(t->hash);
	
	for (k = 0; k < t->nkeys; k++)
	{
		free(t->keys[k]);
	}
	
	free(t->keys);
	
	free(t);
}

void * cconf_table_get(cconf_table_t * t, char * key)
{
	return gdsl_hash_search(t->hash, key);
}

int cconf_table_insert(cconf_table_t * t, void * entry)
{	
	const char * key = key_fcn(entry);
	void * result = gdsl_hash_search(t->hash, key);
	
	if (result != NULL)
		return TABLE_ENTRY_EXISTS;
	
	result = gdsl_hash_insert(t->hash, entry);
	
	if (result == NULL)
		return TABLE_FULL;
		
	t->keys = realloc(t->keys, (t->nkeys + 1) * sizeof(char *));
	
	if (t->keys == NULL)
		return TABLE_FULL;
		
	t->keys[t->nkeys++] = strdup(key);
		
	return TABLE_NO_ERROR;
}

int cconf_table_get_all(cconf_table_t * t, char *** names, void *** items)
{
	int k;
	
	*names = calloc(t->nkeys, sizeof(char *));
	*items = calloc(t->nkeys, sizeof(void *));
	
	for (k = 0; k < t->nkeys; k++)
	{
		(*names)[k] = t->keys[k];
		(*items)[k] = cconf_table_get(t, t->keys[k]);
	}
	
	return t->nkeys;
}
